/*
 * Copyright (C) 2019 Zilliqa
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */

#ifndef ZILLIQA_SRC_LIBBLOCKCHAIN_MICROBLOCK_H_
#define ZILLIQA_SRC_LIBBLOCKCHAIN_MICROBLOCK_H_

#include "BlockBase.h"
#include "libBlockchain/MicroBlockHeader.h"

/// Micro block generated by each sharding committee.
class MicroBlock final : public BlockBase {
  MicroBlockHeader m_header;
  std::vector<TxnHash> m_tranHashes;

 public:
  /// Default constructor.
  MicroBlock() = default;  // creates a dummy invalid placeholder block --
                           // blocknum is maxsize of uint256

  /// Constructor with predefined member values
  template <typename CoSignaturesT, typename TranHashesT>
  MicroBlock(const MicroBlockHeader& header, TranHashesT&& tranHashes,
             CoSignaturesT&& coSigs, uint64_t timestamp = get_time_as_int())
      : BlockBase{header.GetMyHash(), std::forward<CoSignaturesT>(coSigs),
                  timestamp},
        m_header(header),
        m_tranHashes{std::forward<TranHashesT>(tranHashes)} {
    if (m_header.GetNumTxs() != m_tranHashes.size()) {
      LOG_GENERAL(WARNING, "Num of Txns get from header "
                               << m_header.GetNumTxs()
                               << " is not equal to the size of m_tranHashes "
                               << m_tranHashes.size());
    }
  }

  /// Implements the Serialize function inherited from Serializable.
  virtual bool Serialize(zbytes& dst, unsigned int offset) const override;

  /// Implements the Deserialize function inherited from Serializable.
  virtual bool Deserialize(const zbytes& src, unsigned int offset) override;

  /// Implements the Deserialize function inherited from Serializable.
  virtual bool Deserialize(const std::string& src,
                           unsigned int offset) override;

  /// Returns the header component of the microblock.
  const MicroBlockHeader& GetHeader() const noexcept { return m_header; }

  /// Returns the list of transaction hashes.
  const std::vector<TxnHash>& GetTranHashes() const noexcept {
    return m_tranHashes;
  }

  /// Equality operator.
  bool operator==(const MicroBlock& block) const;
};

std::ostream& operator<<(std::ostream& os, const MicroBlock& t);

#endif  // ZILLIQA_SRC_LIBBLOCKCHAIN_MICROBLOCK_H_
